#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         PropertyAccess.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  Defines the PropertyAccess interface, which
#               specifies how GenericObject properties may be 
#               set and retrieved at runtime.
#
# See Also:     PropertyDefinition, PropertyReflection
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Common import *

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## PropertyAccess Interface Definition
class PropertyAccess:
    """
        An interface specifying how properties are requested and set.
    """
        
    #---------------------------------------------------------------#
        
    def getPropertyValue(self, propertyIdentity):
        """
            ABSTRACT: Returns the value of the specified 
            property (if it exists). Returns None if the specified
            property doesn't exist
        """

        # jamesd 2006-05-08 - Added aq_explicit to prevent acquisition of property names
        # ( self.author was returning a plone 2.1 page template )
       
        try:
            here = self.aq_explicit
        except AttributeError:
            # In some cases (i.e. construction) we are passed through without an acquisition wrapper,
            here = self

        #is the property defined?
        if self.isPropertyDefined(propertyIdentity):        

            #is the property actually defined on the object?
            if hasattr(here, propertyIdentity):
                return getattr(here, propertyIdentity)
            else:
                #return the default value here!
                return self.getPropertyDefinition(propertyIdentity).getDefaultValue()
                
        else:
            #TODO: throw and exception here as the property doesn't exist
            return None
        
    #---------------------------------------------------------------#
        
    def setPropertyValue(self, propertyIdentity, value):
        """
            ABSTRACT: Sets the value of the specified property
            to the specified value.  Does nothing if the specified
            property doesn't exist.
        """

        #is the property defined?
        if self.isPropertyDefined(propertyIdentity):        
        
            #get the property definition
            propertyDefinition = self.getPropertyDefinition(propertyIdentity)
        
            #has the value changed (assume yes)
            hasValueChanged = true            
        
            #get the old value
            oldValue = self.getPropertyValue(propertyIdentity)
                
            #will the value change?
            hasValueChanged = oldValue != value
                
            #generate callback event before the property is changed (if the value has changed)
            if hasValueChanged:
                self.onBeforePropertyChange(propertyIdentity, oldValue)
        
            #ensure the type of the value is correct
            try:
                if propertyDefinition.getType() == pt_LONG:
                    value = long(value)                
                elif propertyDefinition.getType() == pt_INTEGER:
                    value = int(value)
                elif propertyDefinition.getType() == pt_FLOAT:
                    value = float(value)
            except:
                #TODO: probably should raise an exception here, as the value isn't of the correct type
                pass
        
            #set the value of the property
            setattr(self, propertyIdentity, value)
                        
            #the property/object has now changed
            self._p_changed = 1
            
            #generate callback event after the property is changed (if the value has changed)
            if hasValueChanged:
                self.onAfterPropertyChange(propertyIdentity, oldValue, value)
            
        else:
            #TODO: throw an exception for unknown properties?
            pass
        
    #---------------------------------------------------------------#

    def onBeforePropertyChange(self, propertyIdentity, newValue):
        """
            Handle when an property is about to change (using the property editor)
            using a call to setPropertyValue (above)
        """

        pass
        
    #---------------------------------------------------------------#

    def onAfterPropertyChange(self, propertyIdentity, oldValue, newValue):
        """
            Handle when an property has changed (using the property editor)
            using a call to setPropertyValue (above)
        """

        pass
            
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation
# (none)
